﻿using System;
using System.IO.Packaging;
using System.Xml;
using System.IO;
using System.Text;
namespace GT.Ultilities
{
	public class Docx
	{
		private const string CONTENT_TYPE_NAMESPACE = @"http://schemas.openxmlformats.org/package/2006/content-types";
		private const string WORD_PROCESSING_ML_NAMESPACE =	@"http://schemas.openxmlformats.org/wordprocessingml/2006/main";
		private const string BODY_XPATH = "/w:document/w:body";
		private string _path;

		public Docx(string path)
		{
			this._path = path;
			
		}
		public string Text()
		{
			using (Package package = Package.Open(this._path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
			{
				PackagePartCollection parts = package.GetParts();
				Uri uri = new Uri("/word/document.xml", UriKind.Relative);
				PackagePart part = package.GetPart(uri);
				Stream s = part.GetStream();
				XmlDocument xdoc = new XmlDocument();
				xdoc.PreserveWhitespace = true;
				xdoc.Load(s);
				s.Close();
				XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
				nsmgr.AddNamespace("w", WORD_PROCESSING_ML_NAMESPACE);
				XmlNode xn = xdoc.DocumentElement.SelectSingleNode(BODY_XPATH, nsmgr);
				return (xn != null) ? Process(xn) : string.Empty;
			}
		}
		private string Process(XmlNode node)
		{
			if (node == null || node.NodeType != XmlNodeType.Element) return string.Empty;
			StringBuilder sb = new StringBuilder();
			foreach (XmlNode xn in node.ChildNodes)
			{
				if (xn.NodeType != XmlNodeType.Element) continue;
				switch (xn.LocalName)
				{
					case "t":
						sb.Append(xn.InnerText.TrimEnd());
						string space = (xn as XmlElement).GetAttribute("xml:space");
						if (!string.IsNullOrEmpty(space) && space == "preserve") sb.Append(' ');
						break;
					case "cr":
					case "br":
						sb.Append(Environment.NewLine);
						break;
					case "tab":
						sb.Append("\t");
						break;
					case "p":
						sb.Append(Process(xn));
						sb.Append(Environment.NewLine);
						sb.Append(Environment.NewLine);
						break;
					default:
						sb.Append(Process(xn));
						break;
				}
			}
			return sb.ToString();
		}
		public static string Text(string path)
		{
			Docx docx = new Docx(path);
			return docx.Text();
		}
	}
}
